
package com.haiyou.common.util.reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;

import com.google.common.collect.Sets;
import com.haiyou.common.util.object.ClassUtils;

/**
 * 
 * @Description:  注解相关工具
 * @author xingyuan
 * @date 2022年7月8日 上午10:28:09
 */
public class AnnotationFinder {

	public static boolean isAnnotation(Class<?> clz, Class<? extends Annotation> annoClz) {
		return clz.isAnnotationPresent(annoClz);
	}

	public static boolean isAnnotation(Method method, Class<? extends Annotation> annoClz) {
		return method.isAnnotationPresent(annoClz);
	}

	public static boolean isAnnotation(Field field, Class<? extends Annotation> annoClz) {
		return field.isAnnotationPresent(annoClz);
	}

	public static <A extends Annotation> A findAnnotation(Class<?> clz, Class<? extends Annotation> annoClz) {
		return (A) clz.getAnnotation(annoClz);
	}

	public static <A extends Annotation> A findAnnotation(Method method, Class<? extends Annotation> annoClz) {
		return (A) method.getAnnotation(annoClz);
	}

	public static <A extends Annotation> A findAnnotation(Field field, Class<? extends Annotation> annoClz) {
		return (A) field.getAnnotation(annoClz);
	}

	/**
	 * 深度查找类注解,包括注解的注解,全部父类,接口的注解
	 * 
	 * @param clz
	 * @return
	 */
	public static <A extends Annotation> A deepFindAnnotation(Class<?> clz, Class<? extends Annotation> annoClz) {
		Set<Annotation> annotations = findAllAnnotations(clz);
		for (Annotation annotation : annotations) {
			if (annotation.annotationType() == annoClz)
				return (A) annotation;
		}
		return null;
	}

	/**
	 * 深度查找方法注解,包括注解的注解
	 * 
	 * @param method
	 * @param annoClz
	 * @return
	 */
	public static <A extends Annotation> A deepFindAnnotation(Method method, Class<? extends Annotation> annoClz) {
		Set<Annotation> annotations = findAllAnnotations(method);
		for (Annotation annotation : annotations) {
			if (annotation.annotationType() == annoClz)
				return (A) annotation;
		}
		return null;
	}

	/**
	 * 深度查找变量注解,包括注解的注解
	 * 
	 * @param field
	 * @param annoClz
	 * @return
	 */
	public static <A extends Annotation> A deepFindAnnotation(Field field, Class<? extends Annotation> annoClz) {
		Set<Annotation> annotations = findAllAnnotations(field);
		for (Annotation annotation : annotations) {
			if (annotation.annotationType() == annoClz)
				return (A) annotation;
		}
		return null;
	}

	public static Set<Annotation> findAllAnnotations(Class<?> clz) {
		Set<Annotation> allAnnotations = Sets.newHashSet();
		Set<Class<?>> classes = ClassUtils.findAllClasses(clz);
		for (Class<?> cls : classes) {
			Annotation[] annotations = cls.getDeclaredAnnotations();
			if (annotations != null && annotations.length > 0) {
				for (int i = 0; i < annotations.length; i++) {
					Annotation annotation = annotations[i];
					Set<Annotation> annotations3 = findAllAnnotations(annotation);
					allAnnotations.addAll(annotations3);
				}
			}
		}
		return allAnnotations;
	}

	public static Set<Annotation> findAllAnnotations(Method method) {
		Set<Annotation> allAnnotations = Sets.newHashSet();
		Annotation[] annotations = method.getDeclaredAnnotations();
		if (annotations != null && annotations.length > 0) {
			for (int i = 0; i < annotations.length; i++) {
				Annotation annotation = annotations[i];
				Set<Annotation> annotations3 = findAllAnnotations(annotation);
				allAnnotations.addAll(annotations3);
			}
		}
		return allAnnotations;
	}

	public static Set<Annotation> findAllAnnotations(Field field) {
		Set<Annotation> allAnnotations = Sets.newHashSet();
		Annotation[] annotations = field.getDeclaredAnnotations();
		if (annotations != null && annotations.length > 0) {
			for (int i = 0; i < annotations.length; i++) {
				Annotation annotation = annotations[i];
				Set<Annotation> annotations3 = findAllAnnotations(annotation);
				allAnnotations.addAll(annotations3);
			}
		}
		return allAnnotations;
	}

	public static Set<Annotation> findAllAnnotations(Annotation annotation) {
		Set<Annotation> annotations = Sets.newHashSet();
		allAnnotations(annotation, annotations);
		return annotations;
	}

	private static void allAnnotations(Annotation annotation, Set<Annotation> annotations) {
		if (annotations == null)
			annotations = Sets.newHashSet();
		if (annotations.contains(annotation))
			return;
		annotations.add(annotation);
		Annotation[] annotations2 = annotation.annotationType().getDeclaredAnnotations();
		if (annotations2 != null && annotations2.length > 0) {
			for (int i = 0; i < annotations2.length; i++) {
				Annotation annotation3 = annotations2[i];
				allAnnotations(annotation3, annotations);
			}
		}
	}

}
